﻿using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Urs.Core;
using Urs.Core.Caching;
using Urs.Data.Domain.Stores;
using Urs.Data.Domain.Users;
using Urs.Data.Domain.Media;
using Urs.Data.Domain.Orders;
using Urs.Data.Domain.Configuration;
using Plugin.Api.Models.Media;
using Plugin.Api.Models.ShoppingCart;
using Urs.Services.Stores;
using Urs.Services.Users;
using Urs.Services.Localization;
using Urs.Services.Media;
using Urs.Services.Orders;
using Urs.Framework.Controllers;

namespace Plugin.Api.Controllers
{
    /// <summary>
    /// 购物车/收藏接口
    /// </summary>
    [ApiAuthorize]
    [ApiVersion("1.0")]
    [Route("api/v{version:apiVersion}/shoppingcart")]
    [ApiController]
    public class ShoppingCartController : BaseApiController
    {
        private readonly ILocalizationService _localizationService;
        private readonly MediaSettings _mediaSettings;
        private readonly IWebHelper _webHelper;
        private readonly ICacheManager _cacheManager;
        private readonly ShoppingCartSettings _shoppingCartSettings;
        private readonly OrderSettings _orderSettings;
        private readonly IOrderTotalCalculationService _orderTotalCalculationService;
        private readonly IGoodsSpecFormatter _goodsSpecFormatter;
        private readonly IGoodsSpecService _goodsSpecService;
        private readonly IPriceCalculationService _priceCalculationService;
        private readonly IGoodsSpecParser _goodsSpecParser;
        private readonly IPictureService _pictureService;
        private readonly IGoodsService _goodsService;
        private readonly IShoppingCartService _shoppingCartService;

        /// <summary>
        /// 构造器
        /// </summary>
        public ShoppingCartController(ILocalizationService localizationService,
            MediaSettings mediaSettings,
            IWebHelper webHelper,
            ICacheManager cacheManager,
            ShoppingCartSettings shoppingCartSettings,
            OrderSettings orderSettings,
            IOrderTotalCalculationService orderTotalCalculationService,
            IGoodsSpecFormatter goodsSpecFormatter,
            IGoodsSpecService goodsSpecService,
            IPriceCalculationService priceCalculationService,
            IGoodsSpecParser goodsSpecParser,
            IPictureService pictureService,
            IGoodsService goodsService,
            IShoppingCartService shoppingCartService)
        {
            this._localizationService = localizationService;
            this._mediaSettings = mediaSettings;
            this._webHelper = webHelper;
            this._cacheManager = cacheManager;
            this._shoppingCartSettings = shoppingCartSettings;
            this._orderSettings = orderSettings;
            this._orderTotalCalculationService = orderTotalCalculationService;
            this._goodsSpecFormatter = goodsSpecFormatter;
            this._goodsSpecService = goodsSpecService;
            this._priceCalculationService = priceCalculationService;
            this._goodsSpecParser = goodsSpecParser;
            this._pictureService = pictureService;
            this._goodsService = goodsService;
            this._shoppingCartService = shoppingCartService;
        }

        #region Utilities

        [NonAction]
        protected MoPicture PrepareCartItemPictureModel(ShoppingCartItem sci, Goods goods,
            int pictureSize, bool showDefaultPicture, string goodsName)
        {
            if (goods == null)
                throw new ArgumentNullException("goods");
             
                //todo
                Picture picture = _pictureService.GetPicturesByGoodsId(goods.Id, 1).FirstOrDefault();

                var model = new MoPicture()
                {
                    NormalUrl = _pictureService.GetPictureUrl(picture, pictureSize, showDefaultPicture)
                };
            return model;
        }

        [NonAction]
        protected string PrepareGoodsSpecs(int goodsId, IList<int> valueIds)
        {
            #region Goods spec
            string selectedAttributes = string.Empty;
            var goodsSpecs = _goodsSpecService.GetGoodsSpecMappingByGoodsId(goodsId);
            foreach (var attribute in goodsSpecs)
            {
                if (valueIds.Contains(attribute.GoodsSpecValueId))
                    selectedAttributes = _goodsSpecParser.AddGoodsSpec(selectedAttributes,
                        attribute, attribute.GoodsSpecValueId.ToString());
            }

            return selectedAttributes;

            #endregion
        }

        [NonAction]
        protected void PrepareShoppingCartModel(User user, MoCart model,
            IList<ShoppingCartItem> cart, bool isEditable = true,
            bool validateCheckoutAttributes = false,
            bool prepareEstimateShippingIfEnabled = true, bool setEstimateShippingDefaultAddress = true,
            bool prepareAndDisplayOrderReviewData = false)
        {
            if (cart == null)
                throw new ArgumentNullException("cart");

            if (model == null)
                throw new ArgumentNullException("model");

            if (cart.Count == 0)
                return;

            #region Simple properties

            //cart warnings
            var cartWarnings = _shoppingCartService.GetShoppingCartWarnings(cart);
            foreach (var warning in cartWarnings)
                model.Warnings.Add(warning);

            #endregion

            #region Cart items

            foreach (var sci in cart)
            {
                var goods = sci.Goods;

                var cartItemModel = new MoCart.MoCartItem()
                {
                    Id = sci.Id,
                    Sku = goods.FormatSku(sci.AttributesXml, _goodsSpecParser),
                    GoodsId = goods.Id,
                    Selected = sci.Selected,
                    Qty = sci.Quantity,
                    AttributeInfo = _goodsSpecFormatter.FormatAttributes(sci.AttributesXml),
                };

                //unit prices
                decimal unitPrice = _priceCalculationService.GetUnitPrice(sci);
                cartItemModel.UnitPrice = PriceFormatter.FormatPrice(unitPrice);
                //subtotal, discount 
                //sub total
                decimal subTotal = _priceCalculationService.GetSubTotal(sci);
                cartItemModel.SubTotal = PriceFormatter.FormatPrice(subTotal);

                //goods name
                cartItemModel.Name = goods.Name;

                //picture
                if (_shoppingCartSettings.ShowGoodsImagesOnShoppingCart)
                {
                    cartItemModel.Picture = PrepareCartItemPictureModel(sci, goods,
                        _mediaSettings.CartThumbPictureSize, true, cartItemModel.Name);
                }

                //item warnings
                var itemWarnings = _shoppingCartService.GetShoppingCartItemWarnings(
                    user,
                    goods,
                    sci.AttributesXml,
                    sci.Quantity,
                    false);
                foreach (var warning in itemWarnings)
                    cartItemModel.Warnings.Add(warning);

                model.Items.Add(cartItemModel);
            }

            #endregion

            #region Cart Total
            var selectedCart = cart.Where(c => c.Selected == true).ToList();
            //total
            decimal orderTotal = _orderTotalCalculationService.GetShoppingCartSubTotal(selectedCart);
            model.OrderTotal = PriceFormatter.FormatPrice(orderTotal);

            #endregion
        }

        #endregion
        /// <summary>
        /// 获取购物车
        /// </summary>
        /// <returns></returns>
        /// <response code="200">成功请求,购物车数据</response>
        [HttpGet("get")]
        [ProducesResponseType(typeof(MoCart), 200)]
        public async Task<ApiResponse<MoCart>> Get()
        {
            var user = RegisterUser;
            if (user == null)
                return ApiResponse<MoCart>.Warn("用户未初始化");

            var data = await Task.Run(() =>
            {
                var cart = user.ShoppingCartItems.ToList();
                var model = new MoCart();
                PrepareShoppingCartModel(user, model, cart);
                return model;
            });
            return ApiResponse<MoCart>.Success(data);
        }

        /// <summary>
        /// 购物车数量
        /// </summary>
        /// <returns></returns>
        /// <response code="200">成功请求,数量</response>
        [HttpGet("count")]
        [ProducesResponseType(typeof(int), 200)]
        public async Task<ApiResponse<int>> GetCartCount()
        {
            var user = RegisterUser;
            if (user == null)
                return ApiResponse<int>.Warn("用户未初始化");

            var data = await Task.Run(() =>
            {
                var count = 0;
                if (user.HasShoppingCartItems)
                {
                    count = user.ShoppingCartItems.Sum(sci => sci.Quantity);
                }
                return count;
            });
            return ApiResponse<int>.Success(data);
        }
        /// <summary>
        /// 添加购物车
        /// </summary>
        /// <param name="model">添加商品对象</param>
        /// <returns></returns>
        [HttpPost("goodstocart")]
        public async Task<ApiResponse<int>> GoodsToCart(MoAddCart model)
        {
            var user = RegisterUser;
            if (user == null)
                return ApiResponse<int>.Warn("用户未初始化");

            var goods = _goodsService.GetGoodsById(model.PId);
            if (goods == null && !goods.Published)
                return ApiResponse<int>.Warn("商品已下架");
            var cartItemId = 0;
            var data = await Task.Run(() =>
            {
                int quantity = model.Qty;
                var warnings = new List<string>();
                string attributes = string.Empty;
                if (!string.IsNullOrWhiteSpace(model.AttrValue))
                {
                    var valueIds = Newtonsoft.Json.JsonConvert.DeserializeObject<List<int>>(model.AttrValue);
                    attributes = PrepareGoodsSpecs(goods.Id, valueIds);
                }
                warnings.AddRange(_shoppingCartService.AddToCart(user,
                    goods, attributes, decimal.Zero, quantity, true, out cartItemId));

                return warnings;
            });
            if (data.Count > 0)
                return ApiResponse<int>.Warn(data.FirstOrDefault());

            return ApiResponse<int>.Success(cartItemId);
        }
        /// <summary>
        /// 批量添加购物车
        /// </summary>
        /// <param name="model">添加商品对象的数组</param>
        /// <returns></returns>
        [HttpPost("goodstocartbluk")]
        public async Task<ApiResponse> GoodssToCart(IList<MoAddCart> model)
        {
            var user = RegisterUser;
            if (user == null)
                return ApiResponse.Warn("用户未初始化");

            var warnings = new List<string>();
            foreach (var item in model)
            {
                var goods = _goodsService.GetGoodsById(item.PId);
                if (goods == null && !goods.Published)
                    continue;

                int quantity = item.Qty;
                string attributes = string.Empty;
                if (!string.IsNullOrWhiteSpace(item.AttrValue))
                {
                    var valueIds = Newtonsoft.Json.JsonConvert.DeserializeObject<List<int>>(item.AttrValue);
                    attributes = PrepareGoodsSpecs(goods.Id, valueIds);
                }
                if (quantity < _shoppingCartSettings.MinimunShoppingCartItemGoodsQuantity)
                {
                    warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.QuantityShouldPositive"), _shoppingCartSettings.MinimunShoppingCartItemGoodsQuantity));
                }

                if (warnings.Count > 0)
                    continue;

                int cartItemId = 0;
                warnings.AddRange(_shoppingCartService.AddToCart(user,
                    goods,  attributes, decimal.Zero, quantity, true, out cartItemId, selected: true));


                if (warnings.Count > 0)
                    continue;
            }
            if (warnings.Count > 0)
                return ApiResponse.Warn(warnings.FirstOrDefault());
            return ApiResponse.Success();
        }

        /// <summary>
        /// 添加购物车到结算
        /// </summary>
        /// <param name="model">添加商品对象</param>
        /// <returns></returns>
        [HttpPost("goodstocheckout")]
        public async Task<ApiResponse<int>> GoodsToCheckout(MoAddCart model)
        {
            var user = RegisterUser;
            if (user == null)
                return ApiResponse<int>.Warn("用户未初始化");

            var goods = _goodsService.GetGoodsById(model.PId);
            if (goods == null || !goods.Published)
                return ApiResponse<int>.Warn("商品已下架");
            var cartItemId = 0;
            var data = await Task.Run(() =>
            {
                int quantity = model.Qty;
                var warnings = new List<string>();
                string attributes = string.Empty;
                if (!string.IsNullOrWhiteSpace(model.AttrValue))
                {
                    var valueIds = Newtonsoft.Json.JsonConvert.DeserializeObject<List<int>>(model.AttrValue);
                    attributes = PrepareGoodsSpecs(goods.Id, valueIds);
                }

                warnings.AddRange(_shoppingCartService.AddToCart(user,
                    goods,  attributes, decimal.Zero, quantity, true, out cartItemId, true, tocheckout: true));

                return warnings;
            });
            if (data.Count > 0)
                return ApiResponse<int>.Warn(data.FirstOrDefault());

            return ApiResponse<int>.Success(cartItemId);
        }
        /// <summary>
        /// 购物车全选
        /// </summary>
        /// <param name="selected">选择:true,不选择:false</param>
        /// <returns></returns>
        [HttpPost("cartallselected")]
        public async Task<ApiResponse> CartAllSelected(bool selected)
        {
            var user = RegisterUser;
            if (user == null)
                return ApiResponse<MoUpdateCart>.Warn("用户未初始化");
            await Task.Run(() =>
           {
               //get shopping cart item
               var cart = user.ShoppingCartItems.ToList();

               _shoppingCartService.UpdateShoppingCartItemSelected(user, cart, selected);

           });
            return ApiResponse.Success();
        }

        /// <summary>
        /// 编辑购物车数量
        /// </summary>
        /// <param name="item">编辑对象</param>
        /// <returns></returns>
        [HttpPost("updatecartitem")]
        public async Task<ApiResponse<MoUpdateCart>> UpdateCartItem(MoUpdateCart item)
        {
            var user = RegisterUser;
            if (user == null)
                return ApiResponse<MoUpdateCart>.Warn("用户未初始化");

            if (item == null)
                return ApiResponse<MoUpdateCart>.NotFound();

            if (item.Quantity < 0)
                return ApiResponse<MoUpdateCart>.Warn("数量不能小于零");

            //get shopping cart item
            var cart = user.ShoppingCartItems.ToList();
            var sci = cart.Where(x => x.Id == item.Id).FirstOrDefault();

            if (sci == null)
                return ApiResponse<MoUpdateCart>.NotFound();

            var data = await Task.Run(() =>
            {
                //update the cart item
                var warnings = new List<string>();
                int newQuantity = item.Quantity;

                warnings.AddRange(_shoppingCartService.UpdateShoppingCartItem(user,
                    sci.Id, newQuantity, item.Selected));
                return warnings;
            });

            if (data.Count > 0)
                return ApiResponse<MoUpdateCart>.Warn(data.FirstOrDefault());

            return ApiResponse<MoUpdateCart>.Success(item);
        }
        /// <summary>
        /// 删除购物车子项
        /// </summary>
        /// <param name="id">购物车子项Id</param>
        /// <returns></returns>
        [HttpPost("removecartitem")]
        public async Task<ApiResponse> RemoveItem(int id)
        {
            var user = RegisterUser;
            if (user == null)
                return ApiResponse<MoUpdateCart>.Warn("用户未初始化");

            await Task.Run(() =>
            {
                var sci = user.ShoppingCartItems.FirstOrDefault(x => x.Id == id);

                _shoppingCartService.DeleteShoppingCartItem(sci, ensureOnlyActiveCheckoutAttributes: true);

            });

            return ApiResponse.Success();
        }

        /// <summary>
        /// 收藏列表/心愿单/关注列表
        /// </summary>
        /// <param name="page">页码（默认：1）</param>
        /// <param name="size">页大小（默认值：12）</param>
        /// <returns>同购物车数据结构</returns>
        [HttpGet("wishlist")]
        public async Task<ApiResponse<MoCart>> Wishlist(int page = 1, int size = 12)
        {
            var user = RegisterUser;
            if (user == null || !user.Active || user.Deleted)
                return ApiResponse<MoCart>.Warn("用户不存在或被禁用");

            var data = await Task.Run(() =>
              {
                  var cart = user.ShoppingCartItems.Take(size).Skip((page - 1) * size).ToList();
                  var model = new MoCart();
                  PrepareShoppingCartModel(user, model, cart);
                  return model;
              });
            return ApiResponse<MoCart>.Success(data);
        }
        /// <summary>
        /// 删除收藏子项
        /// </summary>
        /// <param name="id">收藏子项id</param>
        /// <returns></returns>
        [HttpPost("removewishlistitem")]
        public async Task<ApiResponse> DeleteWishlistItem(int id)
        {
            var user = RegisterUser;
            if (user == null || !user.Active || user.Deleted)
                return ApiResponse<MoCart>.Warn("用户不存在或被禁用");

            await Task.Run(() =>
            {
                //get shopping cart item
                var sci = user.ShoppingCartItems
                    .FirstOrDefault(x => x.Id == id);

                //remove the cart item
                _shoppingCartService.DeleteShoppingCartItem(sci, ensureOnlyActiveCheckoutAttributes: true);
            });
            return ApiResponse.Success();
        }

        /// <summary>
        /// 是否收藏 (1为已收藏，0为未收藏)
        /// </summary>
        /// <param name="pid">商品Id</param>
        /// <returns></returns>
        [HttpPost("iscollect")]
        public async Task<ApiResponse<int>> IsCollect(int pid)
        {
            var user = RegisterUser;
            if (user == null || !user.Active || user.Deleted)
                return ApiResponse<int>.Warn("用户不存在或被禁用");

            var data = await Task.Run(() =>
             {
                 //get shopping cart item
                 var sci = user.ShoppingCartItems.FirstOrDefault(x => x.GoodsId == pid);

                 return sci != null ? 1 : 0;
             });
            return ApiResponse<int>.Success(data);
        }

        /// <summary>
        /// 添加收藏项
        /// </summary>
        /// <param name="model">添加商品对象</param>
        /// <returns></returns>
        [HttpPost("towishlist")]
        public async Task<ApiResponse<int>> AddToWishlist(MoAddCart model)
        {
            var user = RegisterUser;
            if (user == null || !user.Active || user.Deleted)
                return ApiResponse<int>.Warn("用户不存在或被禁用");

            var goods = _goodsService.GetGoodsById(model.PId);
            if (goods == null || !goods.Published)
                return ApiResponse<int>.Warn("商品已下架");
            var cartItemId = 0;
            var data = await Task.Run(() =>
            {
                int quantity = model.Qty;
                var warning = new List<string>();
                string attributes = string.Empty;
                if (!string.IsNullOrWhiteSpace(model.AttrValue))
                {
                    var valueIds = Newtonsoft.Json.JsonConvert.DeserializeObject<List<int>>(model.AttrValue);
                    attributes = PrepareGoodsSpecs(goods.Id, valueIds);
                }
                warning.AddRange(_shoppingCartService.AddToCart(user,
                    goods,attributes, decimal.Zero, quantity, true, out cartItemId));

                return warning;
            });
            if (data.Count > 0)
                return ApiResponse<int>.Warn(data.FirstOrDefault());

            return ApiResponse<int>.Success(cartItemId);
        }

        /// <summary>
        /// 购物车结算
        /// </summary>
        /// <returns></returns>
        [HttpPost("tocheckout")]
        public async Task<ApiResponse> ToCheckout()
        {
            var user = RegisterUser;
            if (user == null || !user.Active || user.Deleted)
                return ApiResponse<ApiResponse>.Warn("用户不存在或被禁用");

            var data = await Task.Run(() =>
            {
                var cart = user.ShoppingCartItems.Where(sci => sci.Selected == true).ToList();
                //validate attributes
                var warnings = _shoppingCartService.GetShoppingCartWarnings(cart);
                return warnings;
            });
            if (data.Count > 0)
                return ApiResponse.Warn(data.FirstOrDefault());

            return ApiResponse.Success();
        }
    }
}
